﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
using ILRuntime.CLR.Method;
using ILRuntime.CLR.TypeSystem;
using ILRuntime.Runtime.Enviorment;
using MongoDB.Bson.IO;
using UnityEngine;
using UnityEngine.EventSystems;

namespace QPEngine
{
    public class Init : EventTrigger
    {
        public static Init Instance;

        public ILRuntime.Runtime.Enviorment.AppDomain AppDomain;

        private IStaticMethod start;
        private IStaticMethod update;
        private IStaticMethod lateUpdate;
        private IStaticMethod fixedUpdate;
        private IStaticMethod onApplicationQuit;
        private IStaticMethod onBeginDrag;
        private IStaticMethod onCancel;
        private IStaticMethod onDeselect;
        private IStaticMethod onDrag;
        private IStaticMethod onDrop;
        private IStaticMethod onEndDrag;
        private IStaticMethod onInitializePotentialDrag;
        private IStaticMethod onMove;
        private IStaticMethod onPointerClick;
        private IStaticMethod onPointerDown;
        private IStaticMethod onPointerEnter;
        private IStaticMethod onPointerExit;
        private IStaticMethod onPointerUp;
        private IStaticMethod onScroll;
        private IStaticMethod onSelect;
        private IStaticMethod onSubmit;
        private IStaticMethod onUpdateSelected;
        private IStaticMethod onApplicationFocus;


      
        private void Start()
        {
            try
            {
                DontDestroyOnLoad(gameObject);
                Instance = this;

                ObjectEvents.Instance.Add("QPEngine", typeof(Init).Assembly);
                if(!AppConst.DebugMode)
                {
                    Log.Debug("非调试模式");
                    this.AppDomain = new ILRuntime.Runtime.Enviorment.AppDomain();

                    ObjectEvents.Instance.LoadHotfixDll();
                    ILHelper.InitILRuntime();

                    this.start = new ILStaticMethod("Hotfix.Init", "Start", 0);
                    this.update = new ILStaticMethod("Hotfix.Init", "Update", 0);
                    this.fixedUpdate = new ILStaticMethod("Hotfix.Init", "FixedUpdate", 0);
                    this.lateUpdate = new ILStaticMethod("Hotfix.Init", "LateUpdate", 0);
                    this.onBeginDrag = new ILStaticMethod("Hotfix.Init", "OnBeginDrag", 1);
                    this.onCancel = new ILStaticMethod("Hotfix.Init", "OnCancel", 1);
                    this.onDeselect = new ILStaticMethod("Hotfix.Init", "OnDeselect", 1);
                    this.onDrag = new ILStaticMethod("Hotfix.Init", "OnDrag", 1);
                    this.onDrop = new ILStaticMethod("Hotfix.Init", "OnDrop", 1);
                    this.onEndDrag = new ILStaticMethod("Hotfix.Init", "OnEndDrag", 1);
                    this.onInitializePotentialDrag = new ILStaticMethod("Hotfix.Init", "OnInitializePotentialDrag", 1);
                    this.onMove = new ILStaticMethod("Hotfix.Init", "OnMove", 1);
                    this.onPointerClick = new ILStaticMethod("Hotfix.Init", "OnPointerClick", 1);
                    this.onPointerDown = new ILStaticMethod("Hotfix.Init", "OnPointerDown", 1);
                    this.onPointerEnter = new ILStaticMethod("Hotfix.Init", "OnPointerEnter", 1);
                    this.onPointerExit = new ILStaticMethod("Hotfix.Init", "OnPointerExit", 1);
                    this.onPointerUp = new ILStaticMethod("Hotfix.Init", "OnPointerUp", 1);
                    this.onScroll = new ILStaticMethod("Hotfix.Init", "OnScroll", 1);
                    this.onSelect = new ILStaticMethod("Hotfix.Init", "OnSelect", 1);
                    this.onSubmit = new ILStaticMethod("Hotfix.Init", "OnSubmit", 1);
                    this.onUpdateSelected = new ILStaticMethod("Hotfix.Init", "OnUpdateSelected", 1);
                    this.onApplicationQuit = new ILStaticMethod("Hotfix.Init", "OnApplicationQuit", 1);
                    this.onApplicationFocus = new ILStaticMethod("Hotfix.Init", "OnApplicationFocus", 1);
                }
                else
                {
                    Log.Debug("调试模式");
                    ObjectEvents.Instance.LoadHotfixDll();
                    Type hotfixInit = ObjectEvents.Instance.HotfixAssembly.GetType("Hotfix.Init");
                    this.start = new MonoStaticMethod(hotfixInit, "Start");
                    this.update = new MonoStaticMethod(hotfixInit, "Update");
                    this.fixedUpdate = new MonoStaticMethod(hotfixInit, "FixedUpdate");
                    this.lateUpdate = new MonoStaticMethod(hotfixInit, "LateUpdate");
                    this.onBeginDrag = new MonoStaticMethod(hotfixInit, "OnBeginDrag");
                    this.onCancel = new MonoStaticMethod(hotfixInit, "OnCancel");
                    this.onDeselect = new MonoStaticMethod(hotfixInit, "OnDeselect");
                    this.onDrag = new MonoStaticMethod(hotfixInit, "OnDrag");
                    this.onDrop = new MonoStaticMethod(hotfixInit, "OnDrop");
                    this.onEndDrag = new MonoStaticMethod(hotfixInit, "OnEndDrag");
                    this.onInitializePotentialDrag = new MonoStaticMethod(hotfixInit, "OnInitializePotentialDrag");
                    this.onMove = new MonoStaticMethod(hotfixInit, "OnMove");
                    this.onPointerClick = new MonoStaticMethod(hotfixInit, "OnPointerClick");
                    this.onPointerDown = new MonoStaticMethod(hotfixInit, "OnPointerDown");
                    this.onPointerEnter = new MonoStaticMethod(hotfixInit, "OnPointerEnter");
                    this.onPointerExit = new MonoStaticMethod(hotfixInit, "OnPointerExit");
                    this.onPointerUp = new MonoStaticMethod(hotfixInit, "OnPointerUp");
                    this.onScroll = new MonoStaticMethod(hotfixInit, "OnScroll");
                    this.onSelect = new MonoStaticMethod(hotfixInit, "OnSelect");
                    this.onSubmit = new MonoStaticMethod(hotfixInit, "OnSubmit");
                    this.onUpdateSelected = new MonoStaticMethod(hotfixInit, "OnUpdateSelected");
                    this.onApplicationFocus = new MonoStaticMethod(hotfixInit, "OnApplicationFocus");
                    this.onApplicationQuit = new MonoStaticMethod(hotfixInit, "OnApplicationQuit");
                }

                Game.Scene.AddComponent<EventComponent>();
                Game.Scene.AddComponent<TimerComponent>();
                Game.Scene.AddComponent<OpcodeTypeComponent>();
                Game.Scene.AddComponent<MessageDispatherComponent>();
                Game.Scene.AddComponent<NetOuterComponent>();
                Game.Scene.AddComponent<ResourcesComponent>();
                Game.Scene.AddComponent<ConfigComponent>();
                //Game.Scene.AddComponent<PlayerComponent>();
                Game.Scene.AddComponent<UnitComponent>();
                Game.Scene.AddComponent<ClientFrameComponent>();
                this.gameObject.AddComponent<MusicManagerHelp>();

                // 进入热更新层
                this.start.Run();

            }
            catch (Exception e)
            {
                Log.Error(e.ToString());
            }
        }

        private void Update()
        {
            this.update.Run();
            ObjectEvents.Instance.Update();
        }

        private void LateUpdate()
        {
            this.lateUpdate.Run();
            ObjectEvents.Instance.LateUpdate();
        }


        public void FixedUpdate()  {  this.fixedUpdate.Run();  }

        public override void OnBeginDrag(PointerEventData eventData) { this.onBeginDrag.Run(eventData); }

        public override void OnCancel(BaseEventData eventData) { this.onCancel.Run(eventData); }

        public override void OnDeselect(BaseEventData eventData) { this.onDeselect.Run(eventData); }

        public override void OnDrag(PointerEventData eventData) { this.onDrag.Run(eventData); }

        public override void OnDrop(PointerEventData eventData) { this.onDrop.Run(eventData); }

        public override void OnEndDrag(PointerEventData eventData) { this.onEndDrag.Run(eventData); }

        public override void OnInitializePotentialDrag(PointerEventData eventData) { this.onInitializePotentialDrag.Run(eventData); }

        public override void OnMove(AxisEventData eventData) { this.onMove.Run(eventData); }

        public override void OnPointerClick(PointerEventData eventData) { this.onPointerClick.Run(eventData); }

        public override void OnPointerDown(PointerEventData eventData) { this.onPointerDown.Run(eventData); }

        public override void OnPointerEnter(PointerEventData eventData) { this.onPointerEnter.Run(eventData); }

        public override void OnPointerExit(PointerEventData eventData) { this.onPointerExit.Run(eventData); }

        public override void OnPointerUp(PointerEventData eventData) { this.onPointerUp.Run(eventData); }

        public override void OnScroll(PointerEventData eventData) { this.onScroll.Run(eventData); }

        public override void OnSelect(BaseEventData eventData) { this.onSelect.Run(eventData); }

        public override void OnSubmit(BaseEventData eventData) { this.onSubmit.Run(eventData); }

        public override void OnUpdateSelected(BaseEventData eventData) { this.onUpdateSelected.Run(eventData); }

        private void OnApplicationFocus(bool isFocus)
        {
            this.onApplicationFocus?.Run(isFocus);
        }


        private void OnApplicationQuit()
        {
            Instance = null;
            Game.Close();
            ObjectEvents.Close();
            this.onApplicationQuit.Run();
            Log.Close();
        }
    }
}